package com.tarena.lbs.common.encoder;

import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.common.enums.PassportResultEnum;
import com.tarena.lbs.common.utils.JsonUtils;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class JwtEncoder<T> {

    private String secretKey;

    private String secret;
    
    // 默认过期时间 2小时
    private long defaultExpiration = 7200000L;

    public JwtEncoder() {
        // 自动生成符合 HS512 要求的密钥
       // this.secretKey = Keys.secretKeyFor(SignatureAlgorithm.HS512);
        this.secretKey = "tarena2024;tarena2024;tarena2024;tarena2024;tarena2024;tarena2024;tarena2024;tarena2024;tarena2024;";
    }
    
    public JwtEncoder(long defaultExpiration) {
        this();
        this.defaultExpiration = defaultExpiration;
    }

    private static final String CLAIM_PAYLOAD = "payload";
    
    public String generateToken(T payload) throws BusinessException {
        return generateToken(payload, defaultExpiration);
    }
    
    public String generateToken(T payload, long expiration) throws BusinessException {
        Map<String, Object> claims = new HashMap<>();
        claims.put(CLAIM_PAYLOAD, JsonUtils.toJson(payload));
        JwtBuilder builder = null;
        try{
            builder = Jwts.builder()
                    .setClaims(claims)
                    .setExpiration(new Date(System.currentTimeMillis() + expiration))
                    .signWith(SignatureAlgorithm.HS512, secretKey.getBytes(StandardCharsets.UTF_8));
        }catch (Exception e){
            log.error("failed to create jwt builders,error message:{}",e.getMessage());
            throw new BusinessException(PassportResultEnum.TOKEN_GENERATE_FAILED);
        }
        return builder.compact();
    }
    
    public boolean isTokenExpired(String token) {
        try {
            Jws<Claims> jws = Jwts.parser()
                    .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                    .parseClaimsJws(token);
            Claims claims = jws.getBody();
            Date expiration = claims.getExpiration();
            return expiration.before(new Date());
        } catch (Exception e) {
            // 如果解析失败，认为token已过期
            return true;
        }
    }
    
    public boolean canTokenBeRefreshed(String token, long refreshThreshold) {
        try {
            Jws<Claims> jws = Jwts.parser()
                    .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                    .parseClaimsJws(token);
            Claims claims = jws.getBody();
            Date expiration = claims.getExpiration();
            Date now = new Date();
            // 如果token还没过期，或者在刷新阈值范围内，可以刷新
            return expiration.after(now) || 
                   (expiration.before(now) && expiration.after(new Date(now.getTime() - refreshThreshold)));
        } catch (Exception e) {
            return false;
        }
    }
    
    public String refreshToken(String token, long expiration) throws BusinessException {
        Jws<Claims> jws = null;
        if (StringUtils.isEmpty(token)){
            return null;
        }
        try {
            jws = Jwts.parser()
                    .setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8))
                    .parseClaimsJws(token);
        } catch(Exception e){
            log.error("jwt parse error:{}",e.getMessage());
            throw new BusinessException(PassportResultEnum.JWT_PARSE_ERROR);
        }
        Claims claims = jws.getBody();
        String loginTokenJson = (String)claims.get(CLAIM_PAYLOAD);
        // 修复类型转换问题
        T payload = (T) JsonUtils.fromJson(loginTokenJson, Object.class);
        // 生成新token
        return generateToken(payload, expiration);
    }
    
    public T getLoginFromToken(String token, Class<? extends T> clazz) throws BusinessException {
        Jws<Claims> jws = null;
        if (StringUtils.isEmpty(token)){
            return null;
        }
        try {
            jws = Jwts.parser().setSigningKey(secretKey.getBytes(StandardCharsets.UTF_8)).parseClaimsJws(token);
        } catch(Exception e){
            log.error("jwt parse error:{}",e.getMessage());
            throw new BusinessException(PassportResultEnum.JWT_PARSE_ERROR);
        }
        Claims claims = (Claims)jws.getBody();
        String loginTokenJson = (String)claims.get(CLAIM_PAYLOAD);
        return JsonUtils.fromJson(loginTokenJson, clazz);
    }

    // 获取默认过期时间
    public long getDefaultExpiration() {
        return defaultExpiration;
    }
}
